/***************************************************************************************************
 * Copyright (c) 2015-2020 Intelligent Network System Ltd. All Rights Reserved. 
 * 
 * This software is the confidential and proprietary information of Founder. You shall not disclose
 * such Confidential Information and shall use it only in accordance with the terms of the 
 * agreements you entered into with Founder. 
***************************************************************************************************/


/***************************************************************************************************
 * INCLUDES
 */
#include "sx127x_dio.h"

#include <stdint.h>
#include <stdbool.h> 
#include <stdio.h>

#include "gpio.h"
#include <time.h>           /* time, clock_gettime, strftime, gmtime */
#include <sys/time.h>       /* timeval */


/***************************************************************************************************
 * DEBUG SWITCH MACROS
 */
#if DEBUG_DIO == 1
#define DEBUG_MSG(str)                fprintf(stderr,"%s:%d: "str, __FUNCTION__, __LINE__)
#define DEBUG_PRINTF(fmt, args...)    fprintf(stderr,"%s:%d: "fmt, __FUNCTION__, __LINE__, args)
#define CHECK_NULL(a)                if(a==NULL){fprintf(stderr,"%s:%d: ERROR: NULL POINTER AS ARGUMENT\n", __FUNCTION__, __LINE__);return -1;}
#else
#define DEBUG_MSG(str)
#define DEBUG_PRINTF(fmt, args...)
#define CHECK_NULL(a)                if(a==NULL){return -1;}
#endif
 
 
 
#define HAL_MAX_PERIOD       (0x80000000)

#define GPIO_PIN(bank, num) (bank*32 + num)

#if 1 // U20
#define DIO0_PIN    (GPIO_PIN(1, 29))
#define DIO1_PIN    (GPIO_PIN(0, 22))
#define DIO2_PIN    (GPIO_PIN(1, 13))
#define DIO3_PIN    (GPIO_PIN(0, 12)) // 2sda
#define NSS_PIN     (123)
#define RESET_PIN   (GPIO_PIN(0, 7))

#define GPIO4_PIN    DIO1_PIN //(GPIO_PIN(0, 13)) // 2scl
#define GPIO5_PIN    (GPIO_PIN(2, 10))
#define GPIO6_PIN    (GPIO_PIN(0, 14)) //(GPIO_PIN(2, 13)) //(GPIO_PIN(0, 14))
#else // U21
#define DIO0_PIN    (GPIO_PIN(1, 14))
#define DIO1_PIN    (GPIO_PIN(0, 27))
#define DIO2_PIN    (GPIO_PIN(1, 15))
#define DIO3_PIN    (GPIO_PIN(2, 3)) 
#define DIO4_PIN    (GPIO_PIN(1, 12))
#define RESET_PIN   (GPIO_PIN(1, 28))

#define NSS_PIN     (123)
#endif 
 
 
 
/*!
 * sx127x_DioDelay__()
 */

/***************************************************************************************************
 *  GLOBAL FUNCTIONS IMPLEMENTATION
 */
 
/*!
 * sx127x_DioInit()
 */
void sx127x_DioInit(void)
{
    // Configure radio DIO as inputs
    // Configure DIO0
    //gpio_export(DIO0_PIN);
	//gpio_set_direction(DIO0_PIN, DIRECTION_INPUT);
    //gpio_set_it_edge(DIO0_PIN, IT_RISING);
    // Configure DIO1
	//gpio_export(DIO1_PIN);
	//gpio_set_direction(DIO1_PIN, DIRECTION_INPUT);
    //gpio_set_it_edge(DIO1_PIN, IT_RISING);    
    // Configure DIO2
    //gpio_export(DIO2_PIN);
	//gpio_set_direction(DIO2_PIN, DIRECTION_INPUT);
    //gpio_set_it_edge(DIO2_PIN, IT_RISING); 

    /* LF RECEIVE */
    gpio_export(GPIO4_PIN);
	gpio_set_direction(GPIO4_PIN, DIRECTION_OUTPUT);
    gpio_set_value(GPIO4_PIN, VALUE_HIGH);

    /* DEFAULT LF */
    gpio_export(GPIO5_PIN);
	gpio_set_direction(GPIO5_PIN, DIRECTION_OUTPUT);
    gpio_set_value(GPIO5_PIN, VALUE_HIGH);

    /* HF RECEIVE */
    gpio_export(GPIO6_PIN);
	gpio_set_direction(GPIO6_PIN, DIRECTION_OUTPUT);
    gpio_set_value(GPIO6_PIN, VALUE_HIGH);
#if 0	
    // REAMARK: DIO3/4/5 configured are connected to IO expander
    // Configure DIO3 as input
    gpio_export(DIO3_PIN);
	gpio_set_direction(DIO3_PIN, DIRECTION_INPUT);    
    // Configure DIO4 as input
    gpio_export(DIO4_PIN);
	gpio_set_direction(DIO4_PIN, DIRECTION_INPUT);    
    // Configure DIO5 as input
	gpio_export(DIO5_PIN);
	gpio_set_direction(DIO5_PIN, DIRECTION_INPUT);
#endif 
    gpio_export(RESET_PIN);
	gpio_set_direction(RESET_PIN, DIRECTION_OUTPUT);
}   /* sx127x_DioInit() */

/*!
 * sx127x_DioDeInit()
 */
void sx127x_DioDeInit(void)
{
    // Configure radio DIO as inputs
    // Configure DIO0
    gpio_unexport(DIO0_PIN);
    // Configure DIO1
	gpio_unexport(DIO1_PIN);   
    // Configure DIO2
    gpio_unexport(DIO2_PIN);

#if 0	
    // REAMARK: DIO3/4/5 configured are connected to IO expander
    gpio_unexport(DIO3_PIN);   
    // Configure DIO4 as input
    gpio_unexport(DIO4_PIN);    
    // Configure DIO5 as input
	gpio_unexport(DIO5_PIN);
#endif  
}   /* sx127x_DioDeInit() */


void sx127x_Gpio4Set( bool a_bReset )
{
    if( a_bReset == true ){
        gpio_set_value(GPIO4_PIN, VALUE_HIGH); /* reset pin = low level */
    }else{
        gpio_set_value(GPIO4_PIN, VALUE_LOW);   /* reset pin = high level */
    }
}

void sx127x_Gpio5Set( bool a_bReset )
{
    if( a_bReset == true ){
        gpio_set_value(GPIO5_PIN, VALUE_HIGH); /* reset pin = low level */
    }else{
        gpio_set_value(GPIO5_PIN, VALUE_LOW);   /* reset pin = high level */
    }
}

void sx127x_Gpio6Set( bool a_bReset )
{
    if( a_bReset == true ){
        gpio_set_value(GPIO6_PIN, VALUE_HIGH); /* reset pin = low level */
    }else{
        gpio_set_value(GPIO6_PIN, VALUE_LOW);   /* reset pin = high level */
    }
}
/*!
 * sx127x_DioReset()
 */
void sx127x_DioReset( bool a_bReset )
{
    if( a_bReset == true ){
        gpio_set_value(RESET_PIN, VALUE_LOW); /* reset pin = low level */
    }else{
        gpio_set_value(RESET_PIN, VALUE_HIGH);   /* reset pin = high level */
    }
}


void sx127x_DioNssSelect( bool a_bReset )
{
    if( a_bReset == true ){
        gpio_set_value(NSS_PIN, VALUE_LOW); /* reset pin = low level */
    }else{
        gpio_set_value(NSS_PIN, VALUE_HIGH);   /* reset pin = high level */
    }
}

/*!
 * sx127x_DioReadDio0()
 */
inline uint8_t sx127x_DioReadDio0( void )
{
	uint32_t ret = 0;
	
	gpio_get_value(DIO0_PIN, &ret);
    return (uint8_t)ret;
}   /* sx127x_DioReadDio0() */

/*!
 * sx127x_DioReadDio1()
 */
inline uint8_t sx127x_DioReadDio1( void )
{
	uint32_t ret = 0;
	
	gpio_get_value(DIO1_PIN, &ret);
	
    return (uint8_t)ret;
}  /* sx127x_DioReadDio1() */

/*!
 * sx127x_DioReadDio2()
 */
inline uint8_t sx127x_DioReadDio2( void )
{
	uint32_t ret = 0;
	
	gpio_get_value(DIO2_PIN, &ret);
	
    return (uint8_t)ret;
}   /* sx127x_DioReadDio2() */

/*!
 * sx127x_DioReadDio3()
 */
inline uint8_t sx127x_DioReadDio3( void )
{
	uint32_t ret = 0;
	
	//gpio_get_value(DIO3_PIN, &ret);
	
    return (uint8_t)ret;
}   /* sx127x_DioReadDio3() */

/*!
 * sx127x_DioReadDio4()
 */
inline uint8_t sx127x_DioReadDio4( void )
{
	uint32_t ret = 0;
	
	//gpio_get_value(DIO4_PIN, &ret);
	
    return (uint8_t)ret;
}   /* sx127x_DioReadDio4() */

/*!
 * sx127x_DioReadDio5()
 */
inline uint8_t sx127x_DioReadDio5( void )
{
	uint32_t ret = 0;
	
	//gpio_get_value(DIO5_PIN, &ret);
	
    return (uint8_t)ret;
}   /* sx127x_DioReadDio5() */


uint32_t sx1278_GetCurrentMs(void)
{
	struct timeval current_unix_time;
	uint32_t time_us;
	uint32_t time_ms;
	
	gettimeofday(&current_unix_time, NULL);
	time_us = current_unix_time.tv_sec * 1000000UL + current_unix_time.tv_usec; /* convert time in us */
	time_ms = time_us/1000;
	//printf("count_ms = %d\n", time_ms);
	return time_ms;
}

int32_t sx1278_HalTimeToTmo( uint32_t a_nTimeout, uint32_t a_nTimeNow )
{
    int32_t i32Delta = 0;
    uint32_t u32Delta = 0;

    u32Delta = a_nTimeout >= a_nTimeNow ? a_nTimeout - a_nTimeNow : a_nTimeNow - a_nTimeout;
    
    if( u32Delta < HAL_MAX_PERIOD ){
        i32Delta = a_nTimeout >= a_nTimeNow ? u32Delta : -u32Delta;
    }else{
        u32Delta = 0xFFFFFFFF - u32Delta + 1;
        i32Delta = a_nTimeout > a_nTimeNow ? -u32Delta : u32Delta;
    }
    
    return i32Delta;
}
/***************************************************************************************************
 * LOCAL FUNCTIONS IMPLEMENTATION
 */
/*!
 * sx127x_DioDelay__()
 */


/***************************************************************************************************
* HISTORY LIST
* 1. Create File by author @ data
*   context: here write modified history
*
***************************************************************************************************/

